home *** CD-ROM | disk | FTP | other *** search
/ BCI NET / BCI NET Dec 94.iso / archives / applications / wp / ged11.lha / Install / data / main / GoldED / API / Dock / main.c < prev    next >
C/C++ Source or Header  |  1994-09-02  |  17KB  |  547 lines

  1. /* -----------------------------------------------------------------------------
  2.  
  3.  GoldED API client example code, ©1994 Dietmar Eilert. Dice:
  4.  
  5.  dcc main.c -// -mRR -r -proto -2.0 -l tmsr.lib -l reqtoolssr.lib -o ram:dock
  6.  
  7.  Note: Compiling this code requires ToolManger includes & ToolManager linker
  8.        libraries. ToolManager is ©1990-1994 Stefan Becker.
  9.  
  10.  The following  example  uses  synchronous  ARexx  communication:  Requests  are
  11.  PutMsg()'ed  to  GoldED's  port,  followed  by a WaitPort() to get the editor's
  12.  response. This works fine since we need no ARexx communication  after  the  API
  13.  link has been established. If there were ARexx communication AFTER the link has
  14.  been established (i.e. after sending the 'API  PORT=...'  command  to  register
  15.  with  GoldED),  we  would  have to use an asynchronous design beeing capable of
  16.  answering incoming API messages while waiting for completion of ARexx  requests
  17.  sent to GoldED.
  18.  
  19.  Note: La compilation de ce code demande les includes de ToolManager et les
  20.        bibliothèques de liaison ToolManager. ToolManager est ©1990-1994
  21.        Stefan Becker.
  22.  
  23.  L'exemple suivant utilise les communications  synchrones  ARexx:  les  demandes
  24.  sont PutMsg()'ées au port de GoldED, suivies par un WaitPort() pour se procurer
  25.  la réponse de l'éditeur. Ceci fonctionne  très  bien  comme  nous  n'avons  pas
  26.  besoin  de communications ARexx après l'établissement de la liaison API. S'il y
  27.  avait eu des communications ARexx  APRES  l'établissement  de  la  liaison  API
  28.  (après  avoir  envoyé  la commande 'API PORT=...' pour s'enregistrer à GoldED),
  29.  nous aurions dû utiliser un système asynchrone étant capable  de  répondre  aux
  30.  messages  API arrivants pendant l'attente de la fin des demandes ARexx envoyées
  31.  à GoldED.
  32.  
  33.   ------------------------------------------------------------------------------
  34. */
  35.  
  36. /// "includes"
  37.  
  38. #define Prototype extern
  39.  
  40. #include <exec/exec.h>
  41. #include <string.h>
  42. #include <stdio.h>
  43. #include <stdlib.h>
  44. #include <dos/dos.h>
  45. #include <dos/rdargs.h>
  46. #include <intuition/intuition.h>
  47. #include <workbench/startup.h>
  48. #include <rexx/errors.h>
  49. #include <rexx/rxslib.h>
  50. #include <libraries/reqtools.h>
  51. #include <utility/tagitem.h>
  52. #include <clib/toolmanager_protos.h>
  53. #include <clib/exec_protos.h>
  54. #include <clib/dos_protos.h>
  55. #include <clib/intuition_protos.h>
  56. #include <clib/rexxsyslib_protos.h>
  57. #include <clib/reqtools_protos.h>
  58.  
  59. #include "golded:api/include/golded.h"
  60.  
  61. // ToolManager objects are a combination of action/image/sound:
  62. // Les objets ToolManager sont une combinaison d'objets action/image/son:
  63.  
  64. struct tmTool {
  65.  
  66.     APTR exec;
  67.     APTR icon;
  68.     APTR sound;
  69. };
  70.  
  71. struct Library *ReqToolsBase;
  72.  
  73. Prototype void   main(int, char **);
  74. Prototype void   HandleAPI(void *, char *, struct TagItem *, UWORD, UWORD);
  75. Prototype ULONG *SendRexxCommand(char *, char *, struct MsgPort *, char *);
  76. Prototype char  *xsprintf(char *, char *);
  77. Prototype struct TagItem *ReadConfig(char *, void *, char *, UWORD *, UWORD *);
  78.  
  79. ///
  80. /// "main"
  81.  
  82. void
  83. main(int argc, char **argv)
  84. {
  85.     const char *version = "$VER: dock 1.4 (" __COMMODORE_DATE__ ")";
  86.  
  87.     if ((argc == 2) || (argc == 3)) {
  88.  
  89.         UBYTE *host, *prefs;
  90.         UWORD  try;
  91.         void  *handle;
  92.  
  93.         prefs = (argc-- == 3) ? argv[1] : "progdir:dock.prefs";
  94.  
  95.         // skip the "HOST=" part:
  96.         // sauter la partie "HOST=":
  97.  
  98.         host = argv[argc] + 5;
  99.  
  100.         // wait for ToolManager startup
  101.         // attendre le départ de ToolManager
  102.  
  103.         for (try = 20; !(handle = AllocTMHandle()) && try; try--)
  104.             Delay(10);
  105.  
  106.         if (handle) {
  107.  
  108.             struct TagItem *dock;
  109.  
  110.             UWORD dockX = ~0, dockY = ~0;
  111.  
  112.             if (dock = ReadConfig(prefs, handle, host, &dockX, &dockY))
  113.                 HandleAPI(handle, host, dock, dockX, dockY);
  114.  
  115.             FreeTMHandle(handle);
  116.         }
  117.         else {
  118.  
  119.             puts("got no TM handle ?!");
  120.             puts("pas de gestion TM ?!");
  121.         }
  122.     }
  123.     else {
  124.  
  125.         puts("syntax error: dock [<config>] HOST=<host>");
  126.         puts("erreur de syntaxe: dock [<config>] HOST=<host>");
  127.     }
  128.  
  129.     exit(0);
  130. }
  131.  
  132. int
  133. wbmain(struct WBStartup *startup)
  134. {
  135.     if (ReqToolsBase = OpenLibrary("reqtools.library", 37)) {
  136.  
  137.         rtEZRequestTags("No executable - to be used as API client", "OK", NULL, NULL, TAG_DONE);
  138.  
  139.         CloseLibrary(ReqToolsBase);
  140.     }
  141. }
  142.  
  143.  
  144. ///
  145. /// "read config"
  146.  
  147. /* -------------------------------- ReadConfig ---------------------------------
  148.  
  149.  Read config file. Return ready-to-use tag array for dock creation or NULL.
  150.  Write dock screen position to <dockX>/<dockY>.
  151.  
  152.  Lire le fichier config. Retourne un tableau de tag prêt-à-être-utilisé pour
  153.  la création du dock ou NULL. Ecrit la position du dock en <dockX>/<dockY>.
  154.  
  155. */
  156.  
  157. struct TagItem *
  158. ReadConfig(prefs, handle, host, dockX, dockY)
  159.  
  160. void  *handle;
  161. char  *prefs, *host;
  162. UWORD *dockX, *dockY;
  163. {
  164.     struct TagItem *dock = NULL;
  165.  
  166.     BPTR config;
  167.  
  168.     if (config = Open(prefs, MODE_OLDFILE)) {
  169.  
  170.         struct RDArgs *rdArgs;
  171.  
  172.         if (rdArgs = AllocDosObject(DOS_RDARGS, NULL)) {
  173.  
  174.             static char buffer[256];
  175.  
  176.             UWORD columns, entries, orientation;
  177.  
  178.             columns     = 1;
  179.             orientation = 0;
  180.             entries     = 0;
  181.  
  182.             while (FGets(config, buffer, 255)) {
  183.  
  184.                 char *cmd;
  185.  
  186.                 for (strcat(buffer, "\12"), cmd = buffer; *cmd && (*cmd != ';'); ++cmd) {
  187.  
  188.                     if ((*cmd != ' ') && (*cmd != 10)) {
  189.  
  190.                         ULONG n, argArray[] = { 0, 0, 0, 0, 0, 0 };
  191.  
  192.                         struct RDArgs *args;
  193.  
  194.                         static struct parser { char *command; char *template; } parser[] = {
  195.  
  196.                             "ADD",  "COMMAND/K/A,AREXX/S,EXEC/S,DIR/K,OUTPUT/K,ICON/K/A",
  197.                             "DOCK", "X/N,Y/N,HORIZONTAL/S,COLUMNS/N",
  198.                              NULL
  199.                         };
  200.  
  201.                         for (n = 0; parser[n].command; ++n) {
  202.  
  203.                             if (!memcmp(cmd, parser[n].command, strlen(parser[n].command))) {
  204.  
  205.                                 cmd += strlen(parser[n].command);
  206.  
  207.                                 rdArgs->RDA_Source.CS_Buffer = cmd;
  208.                                 rdArgs->RDA_Source.CS_Length = strlen(cmd);
  209.                                 rdArgs->RDA_Source.CS_CurChr = 0;
  210.                                 rdArgs->RDA_DAList           = NULL;
  211.                                 rdArgs->RDA_Buffer           = NULL;
  212.  
  213.                                 if (args = ReadArgs(parser[n].template, argArray, rdArgs)) {
  214.  
  215.                                     if (n == 0) {
  216.  
  217.                                         char execName[8], iconName[8];
  218.  
  219.                                         struct TagItem iconTags[] = { TMOP_File, strdup((char *)argArray[5]), TMOP_Data, NULL, TAG_DONE };
  220.  
  221.                                         struct TagItem execTags[] = { 
  222.  
  223.                                             TMOP_Command,    xsprintf((char *)argArray[0], host),
  224.                                             TMOP_ExecType,   argArray[1] ? TMET_ARexx : TMET_CLI,
  225.                                             TMOP_Stack,      8192,
  226.                                             TMOP_CurrentDir, argArray[3] ? strdup((char *)argArray[3]) : NULL,
  227.                                             TMOP_Output,     argArray[4] ? strdup((char *)argArray[4]) : NULL,
  228.                                             TAG_DONE
  229.                                         };
  230.  
  231.                                         sprintf(execName, "e%ld", entries);
  232.                                         sprintf(iconName, "i%ld", entries++);
  233.  
  234.                                         CreateTMObjectTagList(handle, strdup(execName), TMOBJTYPE_EXEC,  execTags);
  235.                                         CreateTMObjectTagList(handle, strdup(iconName), TMOBJTYPE_IMAGE, iconTags);
  236.                                     }
  237.  
  238.                                     else if (n == 1) {
  239.  
  240.                                         if (argArray[0])
  241.                                             *dockX = *(ULONG *)argArray[0];
  242.  
  243.                                         if (argArray[1])
  244.                                             *dockY = *(ULONG *)argArray[1];
  245.  
  246.                                         if (argArray[2])
  247.                                             orientation = 1;
  248.  
  249.                                         if (argArray[3])
  250.                                             columns = *(ULONG *)argArray[3];
  251.                                     }
  252.  
  253.                                     FreeArgs(args);
  254.                                 }
  255.                             }
  256.                         }
  257.  
  258.                         break;
  259.                     }
  260.                 }
  261.  
  262.                 if (entries) {
  263.  
  264.                     if (dock = (struct TagItem *)calloc((entries + 9) * sizeof(struct TagItem), 1)) {
  265.  
  266.                         UWORD n;
  267.  
  268.                         dock[0].ti_Tag  = TMOP_PubScreen;
  269.                         dock[1].ti_Tag  = TMOP_LeftEdge;
  270.                         dock[2].ti_Tag  = TMOP_TopEdge;
  271.                         dock[3].ti_Tag  = TMOP_Activated;
  272.                         dock[4].ti_Tag  = TMOP_Centered;
  273.                         dock[5].ti_Tag  = TMOP_Columns;
  274.                         dock[6].ti_Tag  = TMOP_Vertical;
  275.                         dock[7].ti_Tag  = TMOP_Text;
  276.                         dock[8].ti_Tag  = TAG_DONE;
  277.  
  278.                         dock[3].ti_Data = TRUE;
  279.                         dock[5].ti_Data = columns;
  280.                         dock[6].ti_Data = orientation;
  281.  
  282.                         for (n = 0; n < entries; ++n) {
  283.  
  284.                             struct tmTool *tool;
  285.  
  286.                             if (tool = (struct tmTool *)calloc(sizeof(struct tmTool), 1)) {
  287.  
  288.                                 if ((tool->exec = calloc(8, 1)) && (tool->icon = calloc(8, 1))) {
  289.  
  290.                                     sprintf((char *)tool->exec, "e%ld", n);
  291.                                     sprintf((char *)tool->icon, "i%ld", n);
  292.  
  293.                                     dock[8 + n].ti_Tag  = TMOP_Tool;
  294.                                     dock[8 + n].ti_Data = tool;
  295.                                 }
  296.                             }
  297.                         }
  298.                     }
  299.                 }
  300.  
  301.             }
  302.  
  303.             FreeDosObject(DOS_RDARGS, rdArgs);
  304.         }
  305.  
  306.         Close(config);
  307.     }
  308.     else {
  309.  
  310.         puts("dock.prefs missing");
  311.         puts("dock.prefs manquant");
  312.     }
  313.  
  314.     return(dock);
  315. }
  316.  
  317.  
  318. ///
  319. /// "API management"
  320.  
  321. /* --------------------------------- HandleAPI ---------------------------------
  322.  
  323.  Register with GoldED & handle incoming API messages.
  324.  
  325. */
  326.  
  327. void
  328. HandleAPI(handle, host, dock, dockX, dockY)
  329.  
  330. struct TagItem *dock;
  331. char           *host;
  332. void           *handle;
  333. UWORD          dockX, dockY;
  334. {
  335.     struct MsgPort *replyPort;
  336.  
  337.     if (replyPort = CreateMsgPort()) {
  338.  
  339.         char  command[255];
  340.         ULONG *result;
  341.  
  342.         sprintf(command, "API PORT=%ld MASK=%ld", replyPort, API_CLASS_ROOT | API_CLASS_SCREEN);
  343.  
  344.         if (result = SendRexxCommand(host, command, replyPort, NULL)) {
  345.  
  346.             if (*result == RC_OK) {
  347.  
  348.                 BOOL active = TRUE;
  349.  
  350.                 do {
  351.  
  352.                     struct APIMessage *apiMsg, *nextMsg;
  353.  
  354.                     // API messages might already have arrived since SendRexxCommand() only pulls one message of the port
  355.  
  356.                     while (!(apiMsg = (struct APIMessage *)GetMsg(replyPort)))
  357.                         WaitPort(replyPort);
  358.  
  359.                     do {
  360.  
  361.                         for (nextMsg = apiMsg; nextMsg; nextMsg = nextMsg->api_Next) {
  362.  
  363.                             if (nextMsg->api_State == API_STATE_NOTIFY) {
  364.  
  365.                                 switch (nextMsg->api_Class) {
  366.  
  367.                                     case API_CLASS_ROOT:
  368.  
  369.                                         switch (nextMsg->api_Action) {
  370.  
  371.                                             case API_ACTION_DIE:
  372.  
  373.                                                 active = FALSE;
  374.  
  375.                                                 DeleteTMObject(handle, "dock1");
  376.                                                 break;
  377.  
  378.                                             case API_ACTION_INTRODUCE:
  379.  
  380.                                                 static struct TagItem tags[] = {
  381.  
  382.                                                     API_Client_Name,      "dock",
  383.                                                     API_Client_Copyright, "©1994 Dietmar Eilert",
  384.                                                     API_Client_Purpose,   "ToolManager dock for GoldED",
  385.                                                     TAG_DONE
  386.                                                 };
  387.  
  388.                                                 nextMsg->api_Data = tags;
  389.                                                 break;
  390.  
  391.                                             default:
  392.  
  393.                                                 nextMsg->api_Error = API_ERROR_UNKNOWN;
  394.                                         }
  395.  
  396.                                         break;
  397.  
  398.                                     case API_CLASS_SCREEN:
  399.  
  400.                                         switch (nextMsg->api_Action) {
  401.  
  402.                                             case API_ACTION_HIDE:
  403.  
  404.                                                 DeleteTMObject(handle, "dock1");
  405.                                                 break;
  406.  
  407.                                             case API_ACTION_SHOW:
  408.  
  409.                                                 struct Screen *screen;
  410.  
  411.                                                 if (screen = LockPubScreen(nextMsg->api_Screen)) {
  412.  
  413.                                                     dock[0].ti_Data = nextMsg->api_Screen;
  414.                                                     dock[1].ti_Data = (dockX == ~0) ? screen->Width         : dockX;
  415.                                                     dock[2].ti_Data = (dockY == ~0) ? screen->BarHeight + ((screen->BitMap.Depth == 1) ? 2 : 1) : dockY;
  416.  
  417.                                                     UnlockPubScreen(NULL, screen);
  418.                                                 }
  419.  
  420.                                                 CreateTMObjectTagList(handle, "dock1", TMOBJTYPE_DOCK, dock);
  421.  
  422.                                                 break;
  423.  
  424.                                             default:
  425.  
  426.                                                 nextMsg->api_Error = API_ERROR_UNKNOWN;
  427.                                         }
  428.                                         break;
  429.  
  430.                                     default:
  431.  
  432.                                         nextMsg->api_Error = API_ERROR_UNKNOWN;
  433.                                 }
  434.                             }
  435.                         }
  436.  
  437.                         ReplyMsg((struct Message *)apiMsg);
  438.  
  439.                     } while (apiMsg = (struct APIMessage *)GetMsg(replyPort));
  440.  
  441.                 } while (active);
  442.             }
  443.         }
  444.  
  445.         DeleteMsgPort(replyPort);
  446.     }
  447. }
  448.  
  449.  
  450. ///
  451. /// "misc"
  452.  
  453. /* --------------------------------- xsprintf ----------------------------------
  454.  
  455.  sprintf frontend (malloc buffer); limited to string insertion into string
  456.  
  457.  façade sprintf (malloc tampon); limité à l'insertion de chaînes dans la chaîne
  458.  
  459. */
  460.  
  461. char *
  462. xsprintf(mask, var)
  463.  
  464. char *mask, *var;
  465. {
  466.     char *buffer;
  467.  
  468.     if (buffer = malloc(strlen(mask) + strlen(var)))
  469.         sprintf(buffer, mask, var);
  470.  
  471.     return(buffer);
  472. }
  473.  
  474. ///
  475. /// "ARexx"
  476.  
  477. /* ---------------------------------- SendRexxCommand -------------------------
  478.  
  479.  Send ARexx message & wait for answer. Return pointer to result or NULL.
  480.  
  481.  Envoie un message ARexx & attend une réponse. Retourne un pointeur comme résul-
  482.  tat ou NULL.
  483.  
  484. */
  485.  
  486. ULONG *
  487. SendRexxCommand(port, cmd, replyPort, buffer)
  488.  
  489. char   *cmd, *port, *buffer;
  490. struct MsgPort *replyPort;
  491. {
  492.     struct MsgPort *rexxport;
  493.  
  494.     Forbid();
  495.  
  496.     if (rexxport = FindPort(port)) {
  497.  
  498.         struct RexxMsg *rexxMsg, *answer;
  499.  
  500.         if (rexxMsg = CreateRexxMsg(replyPort, NULL, NULL)) {
  501.  
  502.             if (rexxMsg->rm_Args[0] = CreateArgstring(cmd, strlen(cmd))) {
  503.  
  504.                 static ULONG result;
  505.  
  506.                 rexxMsg->rm_Action = RXCOMM | RXFF_RESULT;
  507.  
  508.                 PutMsg(rexxport, &rexxMsg->rm_Node);
  509.  
  510.                 do {
  511.                     
  512.                     WaitPort(replyPort);
  513.  
  514.                     if (answer = (struct RexxMsg *)GetMsg(replyPort))
  515.                         result = answer->rm_Result1;
  516.  
  517.                 } while (!answer);
  518.  
  519.                 Permit();
  520.  
  521.                 if (answer->rm_Result1 == RC_OK) {
  522.  
  523.                     if (answer->rm_Result2) {
  524.  
  525.                         if (buffer)
  526.                             strcpy(buffer, (char *)answer->rm_Result2);
  527.  
  528.                         DeleteArgstring((char *)answer->rm_Result2);
  529.                     }
  530.                 }
  531.  
  532.                 DeleteArgstring((char *)ARG0(answer));
  533.  
  534.                 DeleteRexxMsg(answer);
  535.  
  536.                 return(&result);
  537.             }
  538.         }
  539.     }
  540.  
  541.     Permit();
  542.  
  543.     return(NULL);
  544. }
  545.  
  546. ///
  547.